unit ctrU1;

interface

uses
  Math, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, ElAES;

type
  TForm1 = class(TForm)
    edtKey: TLabeledEdit;
    memCipher: TMemo;
    lblCipherText: TLabel;
    memPlainText: TMemo;
    lblPlainText: TLabel;
    btnDecrypt: TButton;
    memCheck: TMemo;
    lblCheck: TLabel;
    procedure btnDecryptClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function StringToHex(S: string): string;
var
	i: integer;

begin
  Result := '';

  // Go throught every single characters, and convert them
  // to hexadecimal...
	for i := 1 to Length( S ) do
  	Result := Result + IntToHex( Ord( S[i] ), 2 );
end;

function HexToString(S: string): string;
var
	i: integer;

begin
  Result := '';

  // Go throught every single hexadecimal characters, and convert
  // them to ASCII characters...
  for i := 1 to Length( S ) - 1 do
  begin
    // Only process chunk of 2 digit Hexadecimal...
  	if ((i mod 2) = 1) then
	  	Result := Result + Chr( StrToInt( '0x' + Copy( S, i, 2 )));
  end;
end;

procedure HexToVector8(S: string; out Vec: TAESBuffer);
var
	i: integer;
  x: byte;

begin
  for I := 0 to 15 do
    Vec[i] := 0;

  // Go throught every single hexadecimal characters, and convert
  // them to ASCII characters...
  for i := 1 to Length( S ) do
  begin
    // Only process chunk of 2 digit Hexadecimal...
  	if ((i mod 2) = 1) then begin
      x := StrToInt( '0x' + Copy( S, i, 2 ));
	  	//Vec[i shr 1 - 1] := StrToInt( '0x' + Copy( S, i, 2 ));
      Vec[i shr 1] := x;
    end;
  end;
end;

procedure HexToVector(S: string; out Vec: TAESBuffer);
var
	i: integer;
  x: byte;

begin

  // Go throught every single hexadecimal characters, and convert
  // them to ASCII characters...
  for i := 1 to Length( S ) do
  begin
    // Only process chunk of 2 digit Hexadecimal...
  	if ((i mod 2) = 1) then begin
      x := StrToInt( '0x' + Copy( S, i, 2 ));
	  	//Vec[i shr 1 - 1] := StrToInt( '0x' + Copy( S, i, 2 ));
      Vec[i shr 1] := x;
    end;
  end;
end;

function VectorToHex(Vec: TAESBuffer): string;
var
	i: integer;
begin
  Result := '';
  for i := 0 to 15 do
    Result := Result + IntToHex(Vec[i], 2)
  {SetLength(Result, 32);
  for i := 0 to 15 do
  begin

    Result[i shl 1] := IntToHex(Hi(Vec[i]), 1)[1];
    Result[i shl 1+1] := IntToHex(Lo(Vec[i]), 1)[1];
  end;}
end;


procedure TForm1.btnDecryptClick(Sender: TObject);
var
  Dest: TStringStream;
  Start, Stop: cardinal;
  //Size: integer;
  Key: TAESKey128;
  IV: TAESBuffer;
  EncryptedText: TStrings;
  T, S: string;
  m:array[0..3] of TAESBuffer;
  i, len: byte;

  ExpandedKey: TAESExpandedKey128;

  TempIn, TempOut: TAESBuffer;
  //Vector1, Vector2: TAESBuffer;
begin
  s := StringReplace(memCipher.Text, #13#10, '', [rfReplaceAll]);
  len := Length(s) div 2;
  //ShowMessage('Length of message is: ' + IntToStr(Length(s)));
  // Convert hexadecimal to a strings before decrypting...
  //Source := TStringStream.Create( HexToString( StringReplace(memCipher.Text, #13#10, '', [rfReplaceAll])));
  HexToVector(edtKey.Text, Key);
  {HexToVector8(Copy(S, 1, 16), IV);
  HexToVector(Copy(S, 17, 32), m[0]);
  HexToVector(Copy(S, 49, 32), m[1]);
  HexToVector(Copy(S, 81, 32), m[2]);
  HexToVector(Copy(S, 113, 32), m[3]); }

  HexToVector(Copy(S, 1, 32), IV);
  HexToVector(Copy(S, 33, 32), m[0]);
  HexToVector(Copy(S, 65, 32), m[1]);
  HexToVector(Copy(S, 97, 32), m[2]);
  HexToVector(Copy(S, 129, 32), m[3]);
  //KeySource := TStringStream.Create(HexToString(edtKey.Text));
  //Source.ReadBuffer(IV, 16);
  //KeySource.ReadBuffer(Key, 16);
  Dest   := TStringStream.Create( '' );
  //for i := 0 to 2 do
  //  Source.ReadBuffer(m[i], 16);
  memCheck.Text := 'Key: ' + VectorToHex(Key) +
    #13#10'IV: ' + VectorToHex(IV) +
    #13#10'm[0]: ' + VectorToHex(m[0]) +
    #13#10'm[1]: ' + VectorToHex(m[1]) +
    #13#10'm[2]: ' + VectorToHex(m[2]) +
    #13#10'm[3]: ' + VectorToHex(m[3]) +
    #13#10'Key: ' + UpperCase(edtKey.Text) +
    #13#10'IV: ' + UpperCase(Copy(S, 1, 32)) +
    #13#10'm[0]: ' + UpperCase(Copy(S, 33, 32)) +
    #13#10'm[1]: ' + UpperCase(Copy(S, 65, 32)) +
    #13#10'm[2]: ' + UpperCase(Copy(S, 97, 32)) +
    #13#10'm[3]: ' + UpperCase(Copy(S, 129, 32));

  ExpandAESKeyForEncryption(Key, ExpandedKey);
  //Vector1 := IV;
  T := '';
  for i := 0 to 3 do begin
    TempIn := m[i];
    //Vector2 := TempIn;
    EncryptAES(IV, ExpandedKey, TempOut);
    PLongWord(@TempOut[0])^ := PLongWord(@TempOut[0])^ xor PLongWord(@TempIn[0])^;
    PLongWord(@TempOut[4])^ := PLongWord(@TempOut[4])^ xor PLongWord(@TempIn[4])^;
    PLongWord(@TempOut[8])^ := PLongWord(@TempOut[8])^ xor PLongWord(@TempIn[8])^;
    PLongWord(@TempOut[12])^ := PLongWord(@TempOut[12])^ xor PLongWord(@TempIn[12])^;
    T := T + VectorToHex(TempOut);
    Dest.Write(TempOut, SizeOf(TempOut));
    Inc(IV[15]);

    //Vector1 := Vector2;
  end;
  try
    // Start decryption...
    //Size := Source.Size;
    //Start := GetTickCount;


    // Prepare key...
    //KeyStr := HexToString(edtKey.Text);
    //FillChar(Key, SizeOf(Key), 0);
    //Move(PChar(KeyStr)^, Key, Min(SizeOf(Key), Length(KeyStr)));

    // Decrypt now...
    //DecryptAESStreamCBC(Source, Source.Size - Source.Position, Key, IV, Dest);
    //Stop := GetTickCount;
    //Label8.Caption := IntToStr(Stop - Start) + ' ms';
    //Refresh;

    // Display unencrypted text...
    //setLength(T, 2 * len);
    memPlainText.Text := T + #13#10 + HexToString(T);//Dest.DataString;

  finally
    //Source.Free;
    Dest.Free;
  end;
end;
{var
  Source: TStringStream;
  Dest: TStringStream;
  Start, Stop: cardinal;
  Size: integer;
  Key: TAESKey128;
  IV: TAESBuffer;

begin
  // Encryption
  //Label_Status.Caption := 'Encrypting...';
  //Refresh;
  Source := TStringStream.Create( memCipher.Text );
  Dest   := TStringStream.Create( '' );

  try
    // Save data to memory stream...
    Size := Source.Size;
    Dest.WriteBuffer( Size, SizeOf(Size) );

    // Prepare key...
    FillChar( Key, SizeOf(Key), 0 );
    Move( PChar(edtKey.Text)^, Key, Min( SizeOf( Key ), Length( edtKey.Text )));

    // Start encryption...
    //Start := GetTickCount;
    EncryptAESStreamCBC( Source, 0, Key, Dest );
    //Stop := GetTickCount;
    //Label_Time.Caption := IntToStr(Stop - Start) + ' ms';
    Refresh;

    // Display encrypted text using hexadecimals...
	  Memo_CyperText.Lines.BeginUpdate;
    Memo_CyperText.Text := StringToHex( Dest.DataString );
	  Memo_CyperText.Lines.EndUpdate;

  finally
    Source.Free;
    Dest.Free;
  end;
end;          }

end.
